package com.fdb.efp.nls.service.impl.dxm;

import java.math.BigDecimal;
import java.util.Objects;

import com.fdb.efp.nls.service.vo.queue.NlsProcessBizVO;
import com.fdb.efp.nls.common.ConsoleConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.efp.nls.common.PrdStatEnums;
import com.fdb.efp.nls.service.facade.PrdInfoService;
import com.fdb.efp.nls.service.vo.PrdInfoVO;
import com.fdb.efp.esb.common.constant.EsbBizEnums;
import com.fdb.efp.esb.common.constant.SDicClientConstant;
import com.fdb.efp.esb.common.constant.dxm.DxmEnum;
import com.fdb.efp.esb.common.util.SDicMappingClient;
import com.fdb.efp.esb.service.bo.req.dxm.ReqLoanAdjBizmessage;
import com.fdb.efp.esb.service.bo.req.dxm.ReqLoanAdjLmtNoticeBean;
import com.fdb.efp.esb.service.bo.resp.dxm.RespLoanAdjLmtNoticeBean;
import com.fdb.efp.esb.service.facade.dxm.LoanAdjLmtNoticeService;
import com.fdb.efp.limit.service.facade.LmtAdjustThirdService;
import com.fdb.efp.limit.service.facade.LmtPrdContService;
import com.fdb.efp.limit.service.vo.LmtAdjustThirdVO;
import com.fdb.efp.limit.service.vo.LmtPrdContVO;

/**
 * 额度调整申请判断规则
 * 	1. 判断该客户调整后的额度是否大于客户限额
 * 	2. 进行产品要素判断： 产品状态、授信额度、授信有效期
 * 
 * @author  qiuyf
 * @since 2019年3月12日 下午5:20:23
 * @version 1.0
 */
@Service("lmtAdjAccessRuleService")
public class LmtAdjAccessRuleServiceImpl extends LimitSoltServiceImpl {

	private static final Logger logger = LoggerFactory.getLogger(LmtAdjAccessRuleServiceImpl.class);

	@Autowired
	@Qualifier("prdInfoService")
	private PrdInfoService prdInfoService;

	@Autowired
	@Qualifier("lmtPrdContService")
	private LmtPrdContService lmtPrdContService;

	@Autowired
	@Qualifier("lmtAdjustThirdService")
	private LmtAdjustThirdService lmtAdjustThirdService;

	@Autowired
	@Qualifier("loanAdjLmtNoticeService")
	private LoanAdjLmtNoticeService loanAdjLmtNoticeService;

	@Override
	protected void doExecute(NlsProcessBizVO nlsProcessBizVo, LmtAdjustThirdVO lmtAdjustThirdVo) throws Exception {
		String adjSeq = lmtAdjustThirdVo.getAdjSeq();
		String adjAmtId = lmtAdjustThirdVo.getAdjAmtId();

		logger.info("额度调整申请开始进行规则判断----------会话ID：" + adjSeq + "------------调额申请流水号（唯一标记一次调额）:" + adjAmtId);
		try {
			Objects.requireNonNull(lmtAdjustThirdVo);

			BigDecimal adjResLmt = lmtAdjustThirdVo.getAdjResultLmt();
			/**
			 * 现阶段需求，还没用到客户限制额度的维度去判断产品的调额
			 * @date 2019/04/12
			 * 
			 * 通过状态、客户类型查询客户限制额度
			 *CustomerLimitInfoVO cusLmtInfoVO = new CustomerLimitInfoVO();
			cusLmtInfoVO.setSts(DxmEnum.quotaLmtSts.EFFECT.getVALUE());
			cusLmtInfoVO.setCusType(DxmEnum.cusType.PERSONAL.getVALUE());
			cusLmtInfoVO = customerLimitInfoService.queryByStsAndCusTyp(cusLmtInfoVO);
			if(Objects.isNull(cusLmtInfoVO) || StringUtil.isNullorBank(cusLmtInfoVO.getQuotaLimiAmt().toString())) {
				throw new BizException("获取客户限制额度为空！");
			}
			// 1  判断调整后的额度是否大于客户限制额度
			if(adjResLmt.compareTo(cusLmtInfoVO.getQuotaLimiAmt()) == 1) {
				throw new BizException("调整后额度：" + "【" +adjResLmt + "】" + "大于客户限制额度：" + "【" + cusLmtInfoVO.getQuotaLimiAmt() + "】" + "，调额申请失败！");
			}*/

			// 1. 产品信息校验 
			String prdId = Objects.requireNonNull(lmtAdjustThirdVo.getPrdId());
			PrdInfoVO prdInfoVo = new PrdInfoVO();
			prdInfoVo.setPrdId(prdId);
			prdInfoVo = prdInfoService.queryByPk(prdInfoVo);
			// 1.1 产品最大授信额度判断
			if(adjResLmt.compareTo(prdInfoVo.getCrdAprvMaxAmt()) == 1) {
				nlsProcessBizVo.setRefuseMsg(DxmEnum.DxmRefuseMsg.EXCESS.getKey());
				throw new BizException("调整后额度：" + "【" +adjResLmt + "】" + "大于产品最大授信额度：" + "【" + prdInfoVo.getCrdAprvMaxAmt() + "】" + "，调额申请失败！");
			}
			// 1.2 产品最小授信额度判断
			if(adjResLmt.compareTo(prdInfoVo.getCrdAprvMinAmt()) == -1) {
				nlsProcessBizVo.setRefuseMsg(DxmEnum.DxmRefuseMsg.EXCESS.getKey());
				throw new BizException("调整后额度：" + "【" +adjResLmt + "】" + "小于产品最小授信额度：" + "【" + prdInfoVo.getCrdAprvMinAmt() + "】" + "，调额申请失败！");
			}
			// 1.3 产品状态校验
			PrdStatEnums prdStat = PrdStatEnums.parse(prdInfoVo.getPrdStatus());
			if (!Objects.equals(prdStat, PrdStatEnums.IN_USE)) {
				nlsProcessBizVo.setRefuseMsg(DxmEnum.DxmRefuseMsg.PRD_NOT_USE.getKey());
				throw new BizException("产品： " + prdInfoVo.getPrdName() + " 不是有效状态！");
			}

			/**
			 * 通过渠道编号、产品编号、身份证号、系统当前日期，查询授信协议信息 
			 */
			String channelNo = Objects.requireNonNull(lmtAdjustThirdVo.getChannelNo());
			String certCode = Objects.requireNonNull(lmtAdjustThirdVo.getCertCode());
			String curDate = TimeUtil.getCurDate();
			LmtPrdContVO lmtPrdContVO = new LmtPrdContVO();
			lmtPrdContVO.setChannelNo(channelNo);
			lmtPrdContVO.setPrdId(prdId);
			lmtPrdContVO.setCertCode(certCode);
			lmtPrdContVO.setCurDate(curDate);
			lmtPrdContVO.setLmtStatus(ConsoleConstant.LIMIT_STS_02);
			lmtPrdContVO = lmtPrdContService.qryLmtPrdContByCondition(lmtPrdContVO);

			if(Objects.nonNull(lmtPrdContVO)) {
				// 2. 判断是否已存在授信额度
				if(null==lmtPrdContVO.getLmtAmt()) {
					nlsProcessBizVo.setRefuseMsg(DxmEnum.DxmRefuseMsg.LMT_FAILURED.getKey());
					throw new BizException( "客户不存在授信额度。其身份证号为：" + certCode);
				}

				// 3. 调额申请校验完成，进行后处理
				/** 更新调整状态为：通过  */
				lmtAdjustThirdVo.setAdjStatus(DxmEnum.LoanAdjustSts.PASS.getVALUE());
				lmtAdjustThirdService.updateByPk(lmtAdjustThirdVo);

				/** 更新授信协议表 */
				//授信额度
				lmtPrdContVO.setLmtAmt(adjResLmt);

				/**
				 * 【百度数据问题，导致需求变更 @date 2019/06/05 @author qiuyf】
				 * //可用额度  = 授信额度 - 已用额度 - 预占用额度 【*** 可用额度是可以为负数的 ***】
				 * BigDecimal accAmtTmp = lmtPrdContVO.getOccAmt().toString() == null ? BigDecimal.ZERO : lmtPrdContVO.getOccAmt();
				 * BigDecimal preOccAmtTmp = lmtPrdContVO.getPreOccAmt() == null ? BigDecimal.ZERO : lmtPrdContVO.getPreOccAmt();
				 * lmtPrdContVO.setAvailAmt(adjResLmt.subtract(accAmtTmp).subtract(preOccAmtTmp));
				 */

				//最近更新时间
				lmtPrdContVO.setLastUpdateTime(TimeUtil.getCurrentDateTime());
				lmtPrdContService.updateByPk(lmtPrdContVO);

				// 4. 通知百度额度调整申请结果
				this.lmtAdjCallBack(lmtAdjustThirdVo);
			}else {
				nlsProcessBizVo.setRefuseMsg(DxmEnum.DxmRefuseMsg.LMT_FAILURED.getKey());
				throw new BizException("无法根据【渠道编号】："+channelNo +"；【产品编号】："+prdId +"；【身份证号】："+certCode +"；【系统当前日期】："+curDate +"，查询到客户授信额度信息！");
			}
		} catch (Exception e) {
			logger.error("--------额度调整申请失败：" + e.getMessage());
			nlsProcessBizVo.setExceptionFlag(true);
			nlsProcessBizVo.setExceptionMsg(e);
		} finally {
			logger.info("额度调整申请规则判断结束----------会话ID：" + adjSeq + "------------调额申请流水号（唯一标记一次调额）:" + adjAmtId);
		}
	}

	private void lmtAdjCallBack(LmtAdjustThirdVO lmtAdjustThirdVo) {
		String adjSeq = lmtAdjustThirdVo.getAdjSeq();
		String adjAmtId = lmtAdjustThirdVo.getAdjAmtId();
		logger.info("------------ 额度调整申请结果回调开始，会话ID为：" + adjSeq + "-----------" + "调额申请流水号（唯一标记一次调额）：" + adjAmtId);
		try {
			ReqLoanAdjLmtNoticeBean reqBean = new ReqLoanAdjLmtNoticeBean();
			/* 产品代码  */
			reqBean.setProdCd(SDicMappingClient.getExternalSysDicVal(SDicClientConstant.SYSID_IOP, SDicClientConstant.PRD_CODE, lmtAdjustThirdVo.getPrdId()));
			/* 返回代码  */
			reqBean.setRetCd(DxmEnum.RetCd.SUCCESS.getValue());
			/* 交易模式为“异步” */
			reqBean.setTxnMd(DxmEnum.TxnModel.SYNC.getValue());
			/* 请求标志  = 请求方需要保证永远唯一,响应方据此判断是否重复请求 */
			reqBean.setRepeatRqsBss(lmtAdjustThirdVo.getBdReqSn());
			/* 版本号 */
			reqBean.setVerNo(lmtAdjustThirdVo.getVerNo());
			/* 请求时间戳  */
			reqBean.setRqsTmstmp(TimeUtil.getTimeStampByPattern("yyyyMMddHHmmssSSS"));
			/* 会话ID */
			reqBean.setSessionId(adjSeq);
			/* 通知类型 */     
			reqBean.setAdvType(lmtAdjustThirdVo.getAdvType()+"Callback");

			/** 业务数据组装  start*/
			ReqLoanAdjBizmessage reqBizmessage = new ReqLoanAdjBizmessage();
			/* 机构原因码  */
			reqBizmessage.setInstRsnCd(EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE());
			/* 机构原因码说明  */
			reqBizmessage.setInstRsnCdRmk("调额申请通过！");
			/* 机构策略码 */
			reqBizmessage.setInstPolcyCd(DxmEnum.OrgStrategyCode.PASS_10000.getVALUE());
			/* 确认调额后的金额   */
			reqBizmessage.setCfrmAdjtAmt(lmtAdjustThirdVo.getAdjResultLmt().toString());
			/** 业务数据组装 end */ 
			reqBean.setBizmessage(reqBizmessage);

			RespLoanAdjLmtNoticeBean respBean = loanAdjLmtNoticeService.loanAdjLmtNotice(reqBean);

			logger.info("************* 额度调整申请结果回调返回信息为："+JSON.toJSONString(respBean));
			if(!EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE().equals(respBean.getRetCd()) || !DxmEnum.RetCd.REQ_REPEAT.getValue().equals(respBean.getRetCd())) {
				logger.error("额度调整申请结果回调返回信息出错!");
			}else {
				logger.error("额度调整申请结果回调返回信息成功!");
			}
		} catch (Exception e) {
			logger.error("额度调整申请结果回调出现异常：" + e.getMessage());
		} finally {
			logger.info("------------ 额度调整申请结果回调结束，会话ID为：" + adjSeq + "-----------" + "调额申请流水号（唯一标记一次调额）：" + adjAmtId);
		}
	}

}
